package com.xishu.controller;

import com.xishu.annotation.valid.MethodValidator;
import com.xishu.config.Config;
import com.xishu.entity.Company;
import com.xishu.entity.NameAndId;
import com.xishu.entity.User;
import com.xishu.entity.customer.CompanyConfig;
import com.xishu.entity.plat.UserCompanyMapping;
import com.xishu.entity.shop.*;
import com.xishu.response.ResponseData;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.util.DateUtil;
import com.xishu.util.ServletUtil;
import com.xishu.util.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Api(description = "品类控制器")
@RestController
public class CatalogController implements Tools {
    private static Logger logger = LoggerFactory.getLogger(CatalogController.class);

    @ApiOperation(value = "创建品类")
    @PostMapping(value = ("/user/catalog"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true, checkShopId = true)
    public ResponseData create(@RequestBody Catalog catalog) throws Exception {
        if (isEmpty(catalog.getName()) && isEmpty(catalog.getName_zh()) && isEmpty(catalog.getName_en())) {
            VerifyUtil.throwError(ResponseStatus.INVALID_PARAMETER);
        }

        ZhEnService.getInstance().dealZhEn(catalog);
        return CommonService.getInstance().createObject(catalog, (c) -> {
            try {
                CatalogService.getInstance().resetCatalogShowOrder(c);
            } catch (Exception e) {
                logger.error("e", e);
            }
        });
    }

    @ApiOperation(value = "修改品类")
    @PutMapping(value = ("/user/catalog/modify"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true)
    public ResponseData modify(@RequestBody Catalog catalog) throws Exception {
        //同步修改名称
        if (isNotEmpty(catalog.getName_zh())) {
            catalog.setName(catalog.getName_zh());
        } else if (isNotEmpty(catalog.getName_en())) {
            catalog.setName(catalog.getName_en());
        }

        //是否修改了场景
        boolean modifyScene = isNotEmpty(catalog.getSceneList());
        boolean modifyTimeConfig = isNotEmpty(catalog.getTimeConfigList());
        VerifyUtil.verify(() -> !(modifyScene && modifyTimeConfig));

        boolean sameSceneList = true;
        Collection<NameAndId> addCollectionList = null;
        Collection<NameAndId> cutCollectionList = null;


        if (modifyScene) {
            //有场景的时候，清空时间区间
            catalog.setTimeConfigList(new ArrayList<>());
            //修改了场景，再判断场景是否相同
            Long catalogId = catalog.getId();
            Catalog catalogInDb = CatalogService.getInstance().findCatalogById(catalogId);
            sameSceneList = EqualsService.getInstance().equals(catalogInDb.getSceneList(), catalog.getSceneList());
            if (!sameSceneList) {
                addCollectionList = EqualsService.getInstance().subtract(catalog.getSceneList(), getList(catalogInDb.getSceneList()));
                cutCollectionList = EqualsService.getInstance().subtract(getList(catalogInDb.getSceneList()), catalog.getSceneList());
            }
        }


        Long catalogId = catalog.getId();
        Catalog catalogInDb = CatalogService.getInstance().findCatalogById(catalogId);

        boolean sceneChangeTimeConfig = false;
        //场景跨时间
        if (isNotEmpty(catalog.getTimeConfigList()) && isEmpty(catalogInDb.getTimeConfigList())) {
            sceneChangeTimeConfig = true;
        }

        //时间跨场景
        if (isNotEmpty(catalog.getSceneList()) && isEmpty(catalogInDb.getSceneList())) {
            sceneChangeTimeConfig = true;
        }

        ResponseData responseData = CommonService.getInstance().updateObject(catalog, (c) -> {
            try {
                CatalogService.getInstance().catalogNameSyncToOthers(c.getId());
                CatalogService.getInstance().resetCatalogShowOrder(c);

                if (isNotEmpty(catalog.getName_zh()) || isNotEmpty(catalog.getName_en())) {
                    CatalogService.getInstance().syncToItemName(catalog);
                }
            } catch (Exception e) {
                logger.error("e", e);
            }
        });

        //只要场景跨时间配置就把价格清空
        if (sceneChangeTimeConfig) {
            List<Item> itemList = ItemService.getInstance().findItemByCatalogId(catalog.getId(), null);
            for (Item item : itemList) {
                item.setPrice(null);
                CommonService.getInstance().save(item);
            }
        }


        //有时间配置就把场景清空
        if (modifyTimeConfig) {
            List<Item> itemList = ItemService.getInstance().findItemByCatalogId(catalog.getId(), null);
            for (Item item : itemList) {
                item.setPriceConfigList(new ArrayList<>());
                CommonService.getInstance().save(item);
            }
        }

        //修改了场景列表
        if (modifyScene && !sameSceneList) {
            //新增了场景，添加价格为0，并且关闭
            if (isNotEmpty(addCollectionList)) {
                List<Item> itemList = ItemService.getInstance().findItemByCatalogId(catalog.getId(), null);
                for (Item item : itemList) {
                    for (NameAndId nameAndId : addCollectionList) {
                        Long sceneId = nameAndId.getId();
                        ItemService.getInstance().addScene(item, sceneId);
                    }
                }
            }

            //减少了场景，那么依次将该场景从菜品里面删除
            if (isNotEmpty(cutCollectionList)) {
                List<Item> itemList = ItemService.getInstance().findItemByCatalogId(catalog.getId(), null);
                for (Item item : itemList) {
                    for (NameAndId nameAndId : cutCollectionList) {
                        Long sceneId = nameAndId.getId();
                        ItemService.getInstance().cutScene(item, sceneId);
                    }
                }
            }
        }

        return responseData;
    }

    @ApiOperation(value = "查询品类")
    @PutMapping(value = ("/user/catalog"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData search(@RequestBody Catalog catalog) throws Exception {
        return CommonService.getInstance().searchResponse(catalog, null, (catalogList) -> {
            try {

                if (catalog.getFilterSceneId() != null) {
                    List<Catalog> filterCatalogList = catalogList.stream().filter(c -> {
                        List<Long> sceneIdList = c.getSceneList().stream().map(p -> p.getId()).collect(Collectors.toList());
                        if (sceneIdList.contains(catalog.getFilterSceneId())) {
                            return true;
                        }

                        //如果场景没有包括，那么看是否是配置了时间，配置的时间是否在这个时间内
                        //再过滤品类的时间在场景的时间范围内的品类
                        try {
                            if (isNotEmpty(c.getTimeConfigList())) {
                                return CatalogService.getInstance().isCatalogInSceneTime(catalog.getFilterSceneId(), c);
                            }
                        } catch (Exception e) {
                            logger.error("e", e);
                        }
                        return false;
                    }).collect(Collectors.toList());

                    logger.info("filterCatalogList size is {}", filterCatalogList.size());

                    //再判断有没有菜
                    filterCatalogList = filterCatalogList.stream().filter(c -> {
                        return CatalogService.getInstance().catalogContainItem(c.getId(), catalog.getFilterSceneId());
                    }).collect(Collectors.toList());

                    //如果还在判断是否在线
                    if (getBoolean(catalog.getFilterOnlineItem())) {
                        filterCatalogList = filterCatalogList.stream().filter(c -> {
                            //需要过滤上线的菜品
                            return ItemService.getInstance().countCatalogOnline(c.getId()) != 0;
                        }).collect(Collectors.toList());
                    }

                    return filterCatalogList;
                } else if (getBoolean(catalog.getFilterOnlineItem())) {
                    return catalogList.stream().filter(c -> {
                        //需要过滤上线的菜品
                        return ItemService.getInstance().countCatalogOnline(c.getId()) != 0;
                    }).collect(Collectors.toList());
                } else {
                    logger.info("do not filter the scene list");
                    return catalogList;
                }
            } catch (Exception e) {
                logger.error("e", e);
                return new ArrayList<>();
            }
        });
    }


    @ApiOperation(value = "删除品类")
    @DeleteMapping(value = ("/user/catalog"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true)
    public ResponseData delete(@RequestBody Catalog catalog) throws Exception {
        boolean contain = CatalogService.getInstance().canDelete(catalog.getId());
        VerifyUtil.verify(() -> contain, ResponseStatus.INVALID_PARAMETER);

        return CommonService.getInstance().delete(catalog);
    }

    @ApiOperation(value = "品类是否可以删除")
    @PutMapping(value = ("/user/can/catalog"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(checkShop = true)
    public ResponseData canDelete(@RequestBody Catalog catalog) throws Exception {
        VerifyUtil.verify(() -> isNotEmpty(catalog.getId()));
        boolean containsItem = CatalogService.getInstance().canDelete(catalog.getId());

        return CommonService.getInstance().createResponse(containsItem);
    }

    //    @ApiOperation(value = "导入品类, srcShopId是原分店的ID,desShopId目标分店的ID")
//    @PutMapping(value = ("/user/catalog/import/{srcShopId}/{desShopId}/{delete}"), produces = ("application/json;charset=UTF-8"))
    public ResponseData importCatalog(@PathVariable("srcShopId") Long srcShopId, @PathVariable("desShopId") Long desShopId, @PathVariable(value = "delete", required = false) Boolean delete) throws Exception {
        User user = ServletUtil.getUser();
        VerifyUtil.verify(() -> UserService.getInstance().hasShopPrivilege(user, srcShopId), ResponseStatus.PRIVILEGE);
        VerifyUtil.verify(() -> UserService.getInstance().hasShopPrivilege(user, desShopId), ResponseStatus.PRIVILEGE);
        ImportService importService = ImportService.getInstance();

        if (getBoolean(delete)) {
            importService.deleteCatalog(desShopId);
            importService.deleteItem(desShopId);
        }

        importService.importCatalog(srcShopId, desShopId);
        importService.importItem(srcShopId, desShopId);

        return ResponseData.emptyResponse();
    }

}
